!! Copyright (C) 2009,2010,2011,2012  Marco Restelli
!!
!! This file is part of:
!!   LDGH -- Local Hybridizable Discontinuous Galerkin toolkit
!!
!! LDGH is free software: you can redistribute it and/or modify it
!! under the terms of the GNU General Public License as published by
!! the Free Software Foundation, either version 3 of the License, or
!! (at your option) any later version.
!!
!! LDGH is distributed in the hope that it will be useful, but WITHOUT
!! ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
!! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
!! License for more details.
!!
!! You should have received a copy of the GNU General Public License
!! along with LDGH. If not, see <http://www.gnu.org/licenses/>.
!!
!! author: Marco Restelli                   <marco.restelli@gmail.com>


!>\brief
!!
!! Collect some physical constants as parameters
!!
!! \n
!!
!! This module should not be used directly, but only through the
!! test-case module, so that each test case is free to redefine the
!! phisical constants, for instance to neglect the effects of gravity
!! or Earth rotation. Notice that the reference values are made public
!! as default values for the type \c t_phc.
!<----------------------------------------------------------------------
module mod_physical_constants

!-----------------------------------------------------------------------

 use mod_messages, only: &
   mod_messages_initialized, &
   error,   &
   warning, &
   info

 use mod_kinds, only: &
   mod_kinds_initialized, &
   wp

!-----------------------------------------------------------------------
 
 implicit none

!-----------------------------------------------------------------------

! Module interface

 public :: &
   mod_physical_constants_constructor, &
   mod_physical_constants_destructor,  &
   mod_physical_constants_initialized, &
   t_phc

 private

!-----------------------------------------------------------------------

! Module types and parameters

 ! private members
 real(wp), parameter :: &
   !> Earth parameters
   eradius = 6.37122e6_wp, omega = 7.292e-5_wp, gravity = 9.80616_wp, &
   !> atmospheric air as an ideal gas
   cp = 1004.67_wp, rgas = 287.17_wp, &
   cv = cp-rgas, gamma = cp/cv, kappa = rgas/cp, &
   lgas = -2.0_wp/3.0_wp, & !< Stokes hypothesis
   !> sea level reference pressure
   p_s = 1.0e5_wp, p_sf = 1.0_wp/p_s

 !> physical constant collection
 type t_phc
   !> Earth parameters
   real(wp) :: eradius = eradius
   real(wp) :: omega   = omega
   real(wp) :: gravity = gravity
   !> atmospheric air as an ideal gas
   real(wp) :: cp    = cp
   real(wp) :: rgas  = rgas
   real(wp) :: cv    = cv
   real(wp) :: gamma = gamma
   real(wp) :: kappa = kappa
   real(wp) :: lgas  = lgas
   !> sea level reference pressure
   real(wp) :: p_s  = p_s
   real(wp) :: p_sf = p_sf
 end type t_phc

! Module variables

 ! public members
 logical, protected ::               &
   mod_physical_constants_initialized = .false.
 ! private members
 character(len=*), parameter :: &
   this_mod_name = 'mod_physical_constants'

!-----------------------------------------------------------------------

contains

!-----------------------------------------------------------------------

 subroutine mod_physical_constants_constructor()
  character(len=*), parameter :: &
    this_sub_name = 'constructor'

   !Consistency checks ---------------------------
   if( (mod_messages_initialized.eqv..false.)  .or. &
       (mod_kinds_initialized.eqv..false.) ) then
     call error(this_sub_name,this_mod_name, &
                'Not all the required modules are initialized.')
   endif
   if(mod_physical_constants_initialized.eqv..true.) then
     call warning(this_sub_name,this_mod_name, &
                  'Module is already initialized.')
   endif
   !----------------------------------------------

   mod_physical_constants_initialized = .true.
 end subroutine mod_physical_constants_constructor

!-----------------------------------------------------------------------
 
 subroutine mod_physical_constants_destructor()
  character(len=*), parameter :: &
    this_sub_name = 'destructor'
   
   !Consistency checks ---------------------------
   if(mod_physical_constants_initialized.eqv..false.) then
     call error(this_sub_name,this_mod_name, &
                'This module is not initialized.')
   endif
   !----------------------------------------------

   mod_physical_constants_initialized = .false.
 end subroutine mod_physical_constants_destructor

!-----------------------------------------------------------------------

end module mod_physical_constants

